ロジスティック回帰(Logistic Regression)
Overview
ロジスティック回帰は、最も一般的な線形クラス分類アルゴリズムです。名前に反してロジスティック回帰は、回帰アルゴリズムではなくクラス分類アルゴリズムです。主に二値分類に使われます。
Theory
線形モデルによるクラス分類では、決定境界が入力の線形関数になります。線形関数の予測値を0か1のような離散値でカテゴリ分けします。例えば、予測値が0.5以上ならばカテゴリ1、0.5より小さいならばカテゴリ2のように閾値(ここでは0.5)で分類します。そのために登場するのが、ロジスティック関数 (Logistic Function)、別名シグモイド関数 (Sigmoid Function)です。
ロジスティック関数(シグモイド関数)
$ g(z) = \frac{1}{1 + e^{-z}}
https://gyazo.com/9871badd947ab50675258653c18a502a
$ 0 < g(z) < 1、g(0) = 0.5となるのが特徴的な関数です。また、ロジスティック回帰の予測式は、線形回帰の予測式の出力に、ロジスティック関数を適用したものになります。
ロジスティック回帰の予測式
$ h_\theta(x) = g(\theta_0 + \theta_1x_1 + \theta_2x_2 + \theta_3x_3 + ... + \theta_nx_n) = g(\theta^Tx) = \frac{1}{1 + e^{-\theta^Tx}}
上図と予測式から、予測値は$ \theta^Tx \geq 0のとき1を取り、$ \theta^Tx < 0のとき、0を取っていることがわかります。
ここで最適化問題を考えると、ラベル$ yが$ 1の時は$ h_\theta(x)が最大になって欲しい、ラベル$ yが$ 0の時は$ 1 - h_\theta(x)が最大になって欲しいです。よって目的関数は以下のようになります。
ロジスティック回帰の目的関数(対数尤度関数)
$ J(\theta) = -\frac{1}{m}\sum_{i=1}^{m}(y^{(i)}\log (h_\theta(x^{(i)}) + (1-y^{(i)})\log (1 - h_\theta(x^{(i)})))
$ y = 1もしくは$ y = 0をこの関数に代入すると項が1つになって計算しやすいかと思います。さらに、勾配降下法の更新式は次のようになります。
勾配降下法の更新式
repeat until convergence: {
$ \theta_j := \theta_j - \alpha \frac{\partial}{\partial \theta_j} J(\theta) = \theta_j - \alpha \frac{1}{m}\sum_{i=1}^{m}(h_\theta(x^{(i)}) - y^{(i)}) \cdot x_j^{(i)} $ for j:= 0...n
}
Coding(Classification)
cancerデータセットでモデルを構築・学習・評価する
code: Python
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
cancer = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, stratify=cancer.target, random_state=42)
logreg = LogisticRegression().fit(X_train, y_train)
print('Training set score: {:.3f}'.format(logreg.score(X_train, y_train)))
print('Test set score: {:.3f}'.format(logreg.score(X_test, y_test)))
--------------------------------------------------------------------------
Training set score: 0.955
Test set score: 0.958
--------------------------------------------------------------------------
LogisticRegressionは、デフォルトでL2正則化を行っており、そのパラメータはCで定義されています。Cのデフォルト値は1.0で、Cが大きくなると正則化は弱まります。
https://gyazo.com/00fb3bcae513e94d4c68f9698aac7219
cancerデータセットでパラメータCを調整してモデルを構築・学習・評価・可視化して比較する
code: Python
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
cancer = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, stratify=cancer.target, random_state=42)
# C: 1.0
logreg = LogisticRegression().fit(X_train, y_train)
print('Training set score: {:.3f}'.format(logreg.score(X_train, y_train)))
print('Test set score: {:.3f}'.format(logreg.score(X_test, y_test)))
# C: 100
logreg100 = LogisticRegression(C=100).fit(X_train, y_train)
print('Training set score: {:.3f}'.format(logreg100.score(X_train, y_train)))
print('Test set score: {:.3f}'.format(logreg100.score(X_test, y_test)))
# C: 0.01
logreg001 = LogisticRegression(C=0.01).fit(X_train, y_train)
print('Training set score: {:.3f}'.format(logreg001.score(X_train, y_train)))
print('Test set score: {:.3f}'.format(logreg001.score(X_test, y_test)))
# Cパラメータのモデルへの影響を可視化
plt.plot(logreg.coef_.T, 'o', label='C=1.0')
plt.plot(logreg100.coef_.T, '^', label='C=100')
plt.plot(logreg001.coef_.T, 'v', label='C=0.01')
plt.xticks(range(cancer.data.shape1), cancer.feature_names, rotation=90) plt.hlines(0, 0, cancer.data.shape1) plt.ylim(-5, 5)
plt.xlabel('Feature') # 特徴量
plt.ylabel('Coefficient magnitude') # 係数の大きさ
plt.legend()
plt.show()
--------------------------------------------------------------------------
Training set score: 0.955
Test set score: 0.958
Training set score: 0.972
Test set score: 0.965
Training set score: 0.934
Test set score: 0.930
--------------------------------------------------------------------------
https://gyazo.com/135089bc533f919b12949487fcfceb1c
より解釈しやすいモデルが欲しいなら、L1正則化にするとよいです。パラメータpenaltyを指定するとできます。こうすることで、多くの特徴量の係数がゼロになります。
cancerデータセットでパラメータCを調整してモデルを構築・学習・評価・可視化して比較する
code: Python
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
cancer = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, stratify=cancer.target, random_state=42)
lr_l1 = LogisticRegression(C=C, penalty='l1').fit(X_train, y_train)
print('Training accuracy of l1 logreg with C={:.3f}: {:.2f}'.format(C, lr_l1.score(X_train, y_train)))
print('Test accuracy of l1 logreg with C={:.3f}: {:.2f}'.format(C, lr_l1.score(X_test, y_test)))
plt.plot(lr_l1.coef_.T, marker, label='C={:.3f}'.format(C))
plt.xticks(range(cancer.data.shape1), cancer.feature_names, rotation=90) plt.hlines(0, 0, cancer.data.shape1) plt.ylim(-5, 5)
plt.xlabel('Feature')
plt.ylabel('Coefficient magnitude')
plt.legend(loc=3)
plt.show()
--------------------------------------------------------------------------
Training accuracy of l1 logreg with C=0.010: 0.92
Test accuracy of l1 logreg with C=0.010: 0.93
Training accuracy of l1 logreg with C=1.000: 0.96
Test accuracy of l1 logreg with C=1.000: 0.96
Training accuracy of l1 logreg with C=100.000: 0.99
Test accuracy of l1 logreg with C=100.000: 0.98
--------------------------------------------------------------------------
https://gyazo.com/94a09482622cce6e2b455e51ab43a4fd
Summary
Merit
学習、予測が非常に高速
非常に大きいデータセットにも適用できる
Parameters
正則化パラメータC
デフォルト値は1.0
Cが大きくなると正則化は弱まる
正則化手法決定パラメータpenalty
デフォルトでL2正則化を行う
L1正則化を用いたい場合に、"l1"を指定する